package logger

import (
	"encoding/json"
	"log"
	"os"
	"time"

	"qmp_go_push/conf"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

type LoggerKey string

const (
	RequestLogger LoggerKey = "request"
	BizLogger     LoggerKey = "biz"
	ErrLogger     LoggerKey = "err"
)

type LoggerConfig struct {
	logger         *zap.Logger
	loggerFileName string
	loggerLevel    zapcore.Level
}

var loggerKeyMap = map[LoggerKey]*LoggerConfig{}

func InitApiLogger() {
	initLoggerConfig()
	// zap.NewProductionEncoderConfig() 不用时间格式输出不直接
	// 两者就该字段处理不同 EncodeTime:zapcore.TimeEncoderOfLayout(time.DateTime),
	config := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		FunctionKey:    "fun",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.TimeEncoderOfLayout(time.DateTime),
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
	jsonEncoder := zapcore.NewJSONEncoder(config)

	for _, loggerConfig := range loggerKeyMap {
		// 日志文件配置
		lumberjackLogger := &lumberjack.Logger{
			Filename: loggerConfig.loggerFileName,
			MaxSize:  conf.CONFIG.Log.LogMaxSize, // 文件最大为 1000 MB
			MaxAge:   conf.CONFIG.Log.LogMaxAge,  // 保留 7 天
			Compress: true,                       // 是否压缩备份
		}
		// 文件写入
		fileWrite := zapcore.AddSync(lumberjackLogger)
		// 控制台输出
		consoleWrite := zapcore.AddSync(os.Stdout)
		multiWriteSyncer := zapcore.NewMultiWriteSyncer(fileWrite, consoleWrite)

		core := zapcore.NewCore(
			jsonEncoder,
			multiWriteSyncer,
			loggerConfig.loggerLevel,
		)

		// 添加调用者的位置
		loggerConfig.logger = zap.New(core, zap.AddCaller())
	}

	log.Println("===============初始化Logger配置成功===============")
	for loggerKey, loggerConfig := range loggerKeyMap {
		if loggerConfig.logger != nil {
			log.Println(string(loggerKey) + ":" + loggerConfig.loggerFileName)
		}
	}
	marshalIndent, _ := json.MarshalIndent(&conf.CONFIG.Log, "", "\t")
	log.Println(string(marshalIndent))
	log.Println()
	log.Println()
}

func initLoggerConfig() {
	loggerKeyMap = map[LoggerKey]*LoggerConfig{
		RequestLogger: {
			logger:         &zap.Logger{},
			loggerFileName: conf.CONFIG.Log.LogSavePath + "request.log",
			loggerLevel:    zapcore.InfoLevel,
		},
		BizLogger: {
			logger:         &zap.Logger{},
			loggerFileName: conf.CONFIG.Log.LogSavePath + "biz.log",
			loggerLevel:    zapcore.DebugLevel,
		},
		ErrLogger: {
			logger:         &zap.Logger{},
			loggerFileName: conf.CONFIG.Log.LogSavePath + "err.log",
			loggerLevel:    zapcore.ErrorLevel,
		},
	}
}

func Error(loggerKsy LoggerKey, msg string, fields ...zap.Field) {
	if config, exists := loggerKeyMap[loggerKsy]; exists && config.logger != nil {
		defer config.logger.Sync()
		config.logger.Error(msg, fields...)
	}
}

func Info(loggerKsy LoggerKey, msg string, fields ...zap.Field) {
	if config, exists := loggerKeyMap[loggerKsy]; exists && config.logger != nil {
		defer config.logger.Sync()
		config.logger.Info(msg, fields...)
	}
}
